define([
    'dojo/_base/declare',
    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',
    'dojo/store/Memory',
    'dgrid/OnDemandGrid',
    'dgrid/Selection',
    'dgrid/Keyboard',
    'dgrid/extensions/ColumnResizer',
    'dojo/_base/lang',
    'dojo/_base/Color',
    'dojo/_base/array',

    'dojo/topic',
    'dojo/aspect',
    'dojo/dom',
    'dojo/on',
    'dojo/dom-style',
    'dojo/dom-construct',
    'dojo/dom-class',
    'dijit/form/Button',
    'dijit/form/Form',
    'dijit/form/FilteringSelect',

    'esri/toolbars/draw',
    'esri/layers/GraphicsLayer',
    'esri/layers/FeatureLayer',
    'esri/tasks/QueryTask',
    'esri/tasks/query',
    'esri/graphic',
    'esri/geometry/Extent',
    'esri/renderers/SimpleRenderer',
    'esri/renderers/UniqueValueRenderer',
    'esri/symbols/SimpleLineSymbol',
    'esri/symbols/SimpleFillSymbol',
    'esri/InfoTemplate',
    'esri/symbols/jsonUtils',
    'esri/graphicsUtils',

    '../helper/GeometryHelper',

    'dojo/i18n!./Analyze/nls/resource',
    'dojo/text!./Analyze/templates/Analyze.html',
    'xstyle/css!./Analyze/css/Analyze.css',
    'xstyle/css!./Analyze/css/adw-icons.css'
], function (declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Memory, OnDemandGrid, Selection,
             Keyboard, ColumnResizer, lang, Color, array, topic, aspect, dom, on, Style, domConstruct, domClass,
             Button, Form, FilteringSelect, Draw, GraphicsLayer, FeatureLayer, QueryTask, Query, Graphic, Extent,
             SimpleRenderer, UniqueValueRenderer, SimpleLineSymbol, SimpleFillSymbol, InfoTemplate, symbolUtils,
             graphicsUtils, GeometryHelper, i18n, AnalyzeTemplate) {

    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        widgetsInTemplate: true,
        templateString: AnalyzeTemplate,
        i18n: i18n,
        drawToolbar: null,
        mapClickMode: null,
        currentType: "qjsgc_obj",
        zoomOptions: {
            select: true,
            deselect: false
        },
        defaultResultsSymbols: {
            point: {
                type: 'esriSMS',
                style: 'esriSMSCircle',
                size: 25,
                color: [0, 255, 255, 32],
                angle: 0,
                xoffset: 0,
                yoffset: 0,
                outline: {
                    type: 'esriSLS',
                    style: 'esriSLSSolid',
                    color: [0, 255, 255, 255],
                    width: 2
                }
            },
            polyline: {
                type: 'esriSLS',
                style: 'esriSLSSolid',
                color: [0, 255, 255, 255],
                width: 3
            },
            polygon: {
                type: 'esriSFS',
                style: 'esriSFSSolid',
                color: [0, 255, 255, 32],
                outline: {
                    type: 'esriSLS',
                    style: 'esriSLSSolid',
                    color: [0, 255, 255, 255],
                    width: 3
                }
            }
        },
        defaultSelectionSymbols: {
            point: {
                type: 'esriSMS',
                style: 'esriSMSCircle',
                size: 10,
                color: [255, 0, 0, 32],
                angle: 0,
                xoffset: 0,
                yoffset: 0,
                outline: {
                    type: 'esriSLS',
                    style: 'esriSLSSolid',
                    color: [255, 0, 0, 255],
                    width: 2
                }
            },
            polyline: {
                type: 'esriSLS',
                style: 'esriSLSSolid',
                color: [255, 0, 0, 255],
                width: 3
            },
            polygon: {
                type: 'esriSFS',
                style: 'esriSFSSolid',
                color: [255, 0, 0, 32],
                outline: {
                    type: 'esriSLS',
                    style: 'esriSLSSolid',
                    color: [255, 0, 0, 255],
                    width: 3
                }
            }
        },
        postCreate: function () {
            this.inherited(arguments);
            this.initialzeGlobalVariables();
            this.drawToolbar = new Draw(this.map);
            this.drawToolbar.on('draw-end', lang.hitch(this, 'onDrawToolbarDrawEnd'));
            this.createGraphicLayers();
            this.own(topic.subscribe('mapClickMode/currentSet', lang.hitch(this, 'setMapClickMode')));
            topic.subscribe('analyze/clear', lang.hitch(this, 'clearResults'));
        },

        initialzeGlobalVariables: function () {
            this.queryVariables = {
                url: urls.onemap_url + urls.gis_zxgh_url + '/0?token=' + GLOBAL_TOKEN,
                gridColumns: [
                    {field: 'objid', label: '编号', resizable: false, width: 50, visible: true},
                    {field: 'ename', label: '工程许可证号', visible: true}
                ],
                sort: [
                    {
                        attribute: 'ename',
                        descending: false
                    }
                ]
            };

            this.selectionMode = 'extended';

            if (!this.zoomExtentFactor) {
                this.zoomExtentFactor = 1.5;
            }
            if (!this.pointExtentSize) {
                this.pointExtentSize = 25;
            }
        },

        setQJSGCInfoTemplate: function () {
            var content = '<div class="esriViewPopup"><div class="header">长宁区建设工程</div><div class="hzLine"></div><table class="attrTable" cellpadding="0px" cellspacing="0px"><tbody>'
                + '<tr valign="top"><td class="attrName">图形许可证</td><td class="attrValue">${txxkz}</td></tr>'
                + '<tr valign="top"><td class="attrName">图形档号</td><td class="attrValue">${txdh}</td></tr>'
                + '<tr valign="top"><td class="attrName">图形来源</td><td class="attrValue">${txly}</td></tr>'
                + '<tr valign="top"><td class="attrName">工程许可证号</td><td class="attrValue">${gcxkz}</td></tr>'
                + '<tr valign="top"><td class="attrName">执照影像档号</td><td class="attrValue">${zzyxd}</td></tr>'
                + '<tr valign="top"><td class="attrName">执照档案号</td><td class="attrValue">${zzdah}</td></tr>'
                + '<tr valign="top"><td class="attrName">发证日期</td><td class="attrValue">${fzrq}</td></tr>'
                + '<tr valign="top"><td class="attrName">项目名称</td><td class="attrValue">${xmmc}</td></tr>'
                + '<tr valign="top"><td class="attrName">建设单位</td><td class="attrValue">${jsdw}</td></tr>'
                + '<tr valign="top"><td class="attrName">建设地址</td><td class="attrValue">${jsdz}</td></tr>'
                + '<tr valign="top"><td class="attrName">执照图形档号</td><td class="attrValue">${zztxd}</td></tr>'
                + '<tr valign="top"><td class="attrName">盒数</td><td class="attrValue">${hs}</td></tr>'
                + '<tr valign="top"><td class="attrName">图纸张数</td><td class="attrValue">${tzzs}</td></tr>'
                + '<tr valign="top"><td class="attrName">文件张数</td><td class="attrValue">${wjzs}</td></tr>'
                + '<tr valign="top"><td class="attrName">执照卷数</td><td class="attrValue">${zzjs}</td></tr>'
                + '<tr valign="top"><td class="attrName">竣工卷数</td><td class="attrValue">${jgjs}</td></tr>'
                + '<tr valign="top"><td class="attrName">规划合格证</td><td class="attrValue">${ghhgz}</td></tr>'
                + '<tr valign="top"><td class="attrName">发证面积</td><td class="attrValue">${fzmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">测绘面积</td><td class="attrValue">${chmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">档案合格证</td><td class="attrValue">${dahgz}</td></tr>'
                + '<tr valign="top"><td class="attrName">审核结论单</td><td class="attrValue">${shjld}</td></tr>'
                + '<tr valign="top"><td class="attrName">日期</td><td class="attrValue">${rq}</td></tr>'
                + '<tr valign="top"><td class="attrName">竣工档案号</td><td class="attrValue">${jgdah}</td></tr>'
                + '<tr valign="top"><td class="attrName">序号</td><td class="attrValue">${xh}</td></tr>'
                + '<tr valign="top"><td class="attrName">城档验证号</td><td class="attrValue">${cdyzh}</td></tr>'
                + '<tr valign="top"><td class="attrName">用地影像档号</td><td class="attrValue">${ydyxd}</td></tr>'
                + '<tr valign="top"><td class="attrName">竣工影像档号</td><td class="attrValue">${jgyxd}</td></tr>'
                + '<tr valign="top"><td class="attrName">选址批复</td><td class="attrValue">${xzpf}</td></tr>'
                + '<tr valign="top"><td class="attrName">容积率</td><td class="attrValue">${rjl}</td></tr>'
                + '<tr valign="top"><td class="attrName">用地性质</td><td class="attrValue">${ydxz}</td></tr>'
                + '<tr valign="top"><td class="attrName">建筑性质</td><td class="attrValue">${jzxz}</td></tr>'
                + '<tr valign="top"><td class="attrName">用地许可</td><td class="attrValue">${ydxk}</td></tr>'
                + '<tr valign="top"><td class="attrName">用地面积</td><td class="attrValue">${ydmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">用地批准</td><td class="attrValue">${ydpz}</td></tr>'
                + '<tr valign="top"><td class="attrName">批准面积</td><td class="attrValue">${pzmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">投资计划</td><td class="attrValue">${tzjh}</td></tr>'
                + '<tr valign="top"><td class="attrName">总投资</td><td class="attrValue">${ztz}</td></tr>'
                + '<tr valign="top"><td class="attrName">入库日期</td><td class="attrValue">${rkrq}</td></tr>'
                + '<tr valign="top"><td class="attrName">图形</td><td class="attrValue">${tx}</td></tr>'
                + '<tr valign="top"><td class="attrName">有属性</td><td class="attrValue">${ysx}</td></tr>'
                + '</tbody></table></div>';
            var infoTemplate = new InfoTemplate("长宁区建设工程", content);
            return infoTemplate;
        },

        setSPGCInfoTemplate: function () {
            var content = '<div class="esriViewPopup"><div class="header">长宁市批工程</div><div class="hzLine"></div><table class="attrTable" cellpadding="0px" cellspacing="0px"><tbody>'
                + '<tr valign="top"><td class="attrName">执照档案号</td><td class="attrValue">${zzdah}</td></tr>'
                + '<tr valign="top"><td class="attrName">工程许可证</td><td class="attrValue">${gcxkz}</td></tr>'
                + '<tr valign="top"><td class="attrName">单体编号</td><td class="attrValue">${dtbh}</td></tr>'
                + '<tr valign="top"><td class="attrName">申请号</td><td class="attrValue">${sqh}</td></tr>'
                + '<tr valign="top"><td class="attrName">项目名称</td><td class="attrValue">${xmmc}</td></tr>'
                + '<tr valign="top"><td class="attrName">申请单位</td><td class="attrValue">${sqdw}</td></tr>'
                + '<tr valign="top"><td class="attrName">建筑物名称</td><td class="attrValue">${jzwmc}</td></tr>'
                + '<tr valign="top"><td class="attrName">建筑物幢数</td><td class="attrValue">${jzwzs}</td></tr>'
                + '<tr valign="top"><td class="attrName">建筑性质</td><td class="attrValue">${jzxz}</td></tr>'
                + '<tr valign="top"><td class="attrName">建筑面积</td><td class="attrValue">${jzmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">总建筑面积</td><td class="attrValue">${zjzmj}</td></tr>'
                + '<tr valign="top"><td class="attrName">层数</td><td class="attrValue">${cs}</td></tr>'
                + '<tr valign="top"><td class="attrName">高度</td><td class="attrValue">${gd}</td></tr>'
                + '<tr valign="top"><td class="attrName">区县名</td><td class="attrValue">${qxm}</td></tr>'
                + '<tr valign="top"><td class="attrName">审批单位</td><td class="attrValue">${spdw}</td></tr>'
                + '<tr valign="top"><td class="attrName">档案号</td><td class="attrValue">${dah}</td></tr>'
                + '<tr valign="top"><td class="attrName">关联</td><td class="attrValue">${gl}</td></tr>'
                + '<tr valign="top"><td class="attrName">用途</td><td class="attrValue">${yt}</td></tr>'
                + '<tr valign="top"><td class="attrName">备注</td><td class="attrValue">${bz}</td></tr>'
                + '<tr valign="top"><td class="attrName">年份</td><td class="attrValue">${nf}</td></tr>'
                + '</tbody></table></div>';
            var infoTemplate = new InfoTemplate("长宁区建设工程", content);
            return infoTemplate;
        },

        createGraphicLayers: function () {
            this.polygonSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_DASHDOT, new Color([255, 0, 0]), 2), new Color([0, 0, 0, 0.25]));

            this.polygonGraphics = new GraphicsLayer({
                id: 'anaGraphics_poly',
                title: 'Draw Graphics'
            });
            this.polygonRenderer = new SimpleRenderer(this.polygonSymbol);
            this.polygonRenderer.label = 'User drawn polygons';
            this.polygonRenderer.description = '';
            this.polygonGraphics.setRenderer(this.polygonRenderer);
            this.map.addLayer(this.polygonGraphics);
        },

        connectMapClick: function () {
            // 恢复统计前的鼠标状态
            if ((dojo.hasClass(document.getElementById("panState"), "displayNone"))) {
                topic.publish('mapClickMode/currentSet', 'identify');
            }
            else {
                topic.publish('mapClickMode/setDefault');
            }

            this.disableStopButtons();
        },

        disconnectMapClick: function () {
            this.clearGraphics();
            topic.publish('mapClickMode/setCurrent', 'draw');
            this.enableStopButtons();
        },

        setMapClickMode: function (mode) {
            this.mapClickMode = mode;
        },

        selectByRectangle: function () {
            this.disconnectMapClick();
            this.drawToolbar.activate(Draw.EXTENT);
            this.drawModeTextNode.innerText = this.i18n.labels.rectangle;
        },

        selectByPolygon: function () {
            this.disconnectMapClick();
            this.drawToolbar.activate(Draw.POLYGON);
            this.drawModeTextNode.innerText = this.i18n.labels.polygon;
        },

        stopDrawing: function () {
            this.drawToolbar.deactivate();
            this.drawModeTextNode.innerText = this.i18n.labels.currentDrawModeNone;
            this.connectMapClick();
        },

        disableStopButtons: function () {
            this.stopDrawingButton.set('disabled', true);
            this.eraseDrawingButton.set('disabled', !this.noGraphics());
        },

        enableStopButtons: function () {
            this.stopDrawingButton.set('disabled', false);
            this.eraseDrawingButton.set('disabled', !this.noGraphics());
        },

        noGraphics: function () {
            if (this.polygonGraphics.graphics.length > 0) {
                return true;
            } else {
                return false;
            }
            return false;
        },

        onDrawToolbarDrawEnd: function (evt) {
            this.drawToolbar.deactivate();
            this.drawModeTextNode.innerText = this.i18n.labels.currentDrawModeNone;
            var graphic;
            switch (evt.geometry.type) {
                case 'extent':
                case 'polygon':
                    graphic = new Graphic(evt.geometry);
                    this.polygonGraphics.add(graphic);
                    break;
                default:
                    break;
            }
            this.connectMapClick();

            this.createOrResetResultsGrid();
            this.displayFindMessage(this.i18n.searching);

            this.executeQueryTask(evt.geometry);
        },

        displayFindMessage: function (message) {
            domConstruct.empty(this.findResultsNode);
            this.findResultsNode.innerHTML = message;
            this.findResultsNode.style.display = 'block';
        },

        queryLayerChange: function (value) {
            this.currentType = this.typeDijit.value;

            if (this.currentType === 'qjsgc_obj') {
                this.queryVariables.url = urls.onemap_url + urls.gis_zxgh_url + '/0?token=' + GLOBAL_TOKEN;
                this.graphicsLayer.setInfoTemplate(this.setQJSGCInfoTemplate());
            } else if (this.currentType === 'spgc_obj') {
                this.queryVariables.url = urls.onemap_url + urls.gis_zxgh_url + '/1?token=' + GLOBAL_TOKEN;
                this.graphicsLayer.setInfoTemplate(this.setSPGCInfoTemplate());
            }
        },

        executeQueryTask: function (geometry) {
            var query = new Query();
            query.outSpatialReference = this.map.spatialReference;
            query.geometry = geometry;
            query.returnGeometry = true;
            query.outFields = ["*"];
            var queryTask = new QueryTask(this.queryVariables.url);
            var that = this;
            queryTask.execute(query, function (results) {
                var resultText = that.i18n.noResultsLabel;
                that.results = results.features;
                if (that.results.length > 0) {
                    resultText = that.i18n.resultsLabel.labelPrefix + ' ' + that.results.length + ' ' + that.i18n.resultsLabel.labelSuffix;
                    that.createGraphicsLayerAndSymbols();
                    that.parseGridColumnProperties();
                    that.addResultsToGraphicsLayer();
                    that.zoomToGraphics(that.graphicsLayer.graphics);
                    that.showResultsGrid();
                }
                that.displayFindMessage(resultText);
            });
        },
        createGraphicsLayerAndSymbols: function () {
            if (!this.graphicsLayer) {
                this.graphicsLayer = this.createGraphicsLayer();
            } else {
                if (this.currentType === 'qjsgc_obj') {
                    this.graphicsLayer.setInfoTemplate(this.setQJSGCInfoTemplate());
                } else if (this.currentType === 'spgc_obj') {
                    this.graphicsLayer.setInfoTemplate(this.setSPGCInfoTemplate());
                }
            }
            if (!this.graphicsSymbols) {
                this.graphicsSymbols = this.createGraphicsSymbols();
            }
        },
        createGraphicsLayer: function () {
            var graphicsLayer = new GraphicsLayer({
                id: this.id + '_anaGraphics',
                title: 'Analyze'
            });
            if (this.currentType === 'qjsgc_obj') {
                graphicsLayer.setInfoTemplate(this.setQJSGCInfoTemplate());
            } else if (this.currentType === 'spgc_obj') {
                graphicsLayer.setInfoTemplate(this.setSPGCInfoTemplate());
            }
            graphicsLayer.on('click', lang.hitch(this, 'onGraphicsLayerClick'));
            this.map.addLayer(graphicsLayer);
            return graphicsLayer;
        },
        onGraphicsLayerClick: function (event) {
            var zoomOnSelect = this.zoomOptions.select;
            this.zoomOptions.select = false;
            var row = this.resultsGrid.row(event.graphic.storeid);
            this.resultsGrid.select(row);
            this.resultsGrid.focus(row.element);
            row.element.focus();
            this.zoomOptions.select = zoomOnSelect;
        },
        createGraphicsSymbols: function () {
            var graphicSymbols = {}, resultSymbolDefinitions, selectionSymbolDefinitions;
            resultSymbolDefinitions = lang.mixin(this.defaultResultsSymbols, this.resultsSymbols || {});
            graphicSymbols.resultsSymbols = {};
            graphicSymbols.resultsSymbols.point = symbolUtils.fromJson(resultSymbolDefinitions.point);
            graphicSymbols.resultsSymbols.polyline = symbolUtils.fromJson(resultSymbolDefinitions.polyline);
            graphicSymbols.resultsSymbols.polygon = symbolUtils.fromJson(resultSymbolDefinitions.polygon);
            selectionSymbolDefinitions = lang.mixin(
                this.defaultSelectionSymbols, this.selectionSymbols || {}
            );
            graphicSymbols.selectionSymbols = {};
            graphicSymbols.selectionSymbols.point = symbolUtils.fromJson(selectionSymbolDefinitions.point);
            graphicSymbols.selectionSymbols.polyline = symbolUtils.fromJson(selectionSymbolDefinitions.polyline);
            graphicSymbols.selectionSymbols.polygon = symbolUtils.fromJson(selectionSymbolDefinitions.polygon);
            return graphicSymbols;
        },
        parseGridColumnProperties: function () {
            if (this.queryVariables.gridColumns) {
                array.forEach(
                    this.results, function (result) {
                        array.forEach(
                            this.queryVariables.gridColumns, function (column) {
                                function shouldGetValueFromAttributes(col, res) {
                                    if (col.field && !result.hasOwnProperty(col.field) && res.attributes.hasOwnProperty(col.field)) {
                                        return true;
                                    }
                                    return false;
                                }

                                function shouldGetValueFromGetFunction(col, res) {
                                    if (col.field && !res.hasOwnProperty(col.field) && col.get) {
                                        return true;
                                    }
                                    return false;
                                }

                                if (shouldGetValueFromAttributes(column, this)) {
                                    this[column.field] = this.attributes[column.field];
                                } else if (shouldGetValueFromGetFunction(column, this)) {
                                    this[column.field] = column.get(this);
                                }
                            }, result
                        );
                    }, this
                );
            }
        },
        addResultsToGraphicsLayer: function () {
            var unique = 0;
            array.forEach(
                this.results, function (result) {
                    result.id = unique;
                    result.storeid = result.id;
                    unique++;
                    this.setGraphicSymbol(result, false);
                    this.graphicsLayer.add(result);
                }, this
            );
        },
        showResultsGrid: function () {
            this.resultsGrid.store.setData(this.results);
            this.resultsGrid.refresh();
            var lyrDisplay = 'none';

            this.resultsGrid.styleColumn('layerName', 'display:' + lyrDisplay);
            this.findResultsGrid.style.display = 'block';
        },
        setGraphicSymbol: function (graphic, isSelected) {
            var symbol = isSelected ? this.graphicsSymbols.selectionSymbols[graphic.geometry.type] : this.graphicsSymbols.resultsSymbols[graphic.geometry.type];
            graphic.setSymbol(symbol);
        },


        createOrResetResultsGrid: function () {
            if (!this.resultsGrid) {
                this.createResultsStore();
                this.createResultsGrid();
                this.attachStandardEventHandlersToResultsGrid();
            }
            this.clearResultsGrid();
            this.clearFeatures();
            this.resetResultsGridColumns();
            this.resetResultsGridSort();
            this.resetGridSelectionMode();
            this.attachCustomEventHandlersToResultsGrid();
        },
        createResultsStore: function () {
            if (!this.resultsStore) {
                this.resultsStore = new Memory({
                    idProperty: 'id',
                    data: []
                });
            }
        },
        createResultsGrid: function () {
            var Grid = declare([OnDemandGrid, Keyboard, Selection, ColumnResizer]);
            this.resultsGrid = new Grid({
                selectionMode: this.selectionMode,
                cellNavigation: false,
                showHeader: true,
                store: this.resultsStore
            }, this.findResultsGrid);
            this.resultsGrid.startup();
        },
        attachStandardEventHandlersToResultsGrid: function () {
            if (!this.resultsGrid) {
                return;
            }
            this.own(
                this.resultsGrid.on('dgrid-select', lang.hitch(this, 'onResultsGridSelect'))
            );
            this.own(
                this.resultsGrid.on('dgrid-deselect', lang.hitch(this, 'onResultsGridDeselect'))
            );
            this.own(
                this.resultsGrid.on('.dgrid-row:dblclick', lang.hitch(this, 'onResultsGridRowClick'))
            );
        },
        attachCustomEventHandlersToResultsGrid: function () {
            if (!this.resultsGrid) {
                return;
            }
            array.forEach(this.currentQueryEventHandlers, function (handler) {
                handler.handle.remove();
            });
            var queryEventHandlers = this.queryVariables.customGridEventHandlers || [];
            array.forEach(queryEventHandlers, lang.hitch(this, function (handler) {
                handler.handle = this.resultsGrid.on(handler.event, lang.hitch(this, handler.handler));
            }));
            this.currentQueryEventHandlers = queryEventHandlers;
        },
        onResultsGridSelect: function (event) {
            array.forEach(
                event.rows, lang.hitch(
                    this, function (row) {
                        var feature = row.data;
                        this.setGraphicSymbol(feature, true);
                        if (feature && feature.getDojoShape()) {
                            feature.getDojoShape().moveToFront();
                        }
                    }
                )
            );
            this.graphicsLayer.redraw();
            if (this.zoomOptions.select) {
                this.zoomToSelectedGraphics();
            }
        },
        onResultsGridDeselect: function (event) {
            array.forEach(
                event.rows, lang.hitch(
                    this, function (row) {
                        var feature = row.data;
                        this.setGraphicSymbol(feature, false);
                    }
                )
            );
            this.graphicsLayer.redraw();
            if (this.zoomOptions.deselect) {
                this.zoomToSelectedGraphics();
            }
        },
        onResultsGridRowClick: function (event) {
            var row = this.resultsGrid.row(event);
            var feature = row.data;
            setTimeout(lang.hitch(this, function () {
                if (this.resultsGrid.selection.hasOwnProperty(row.id)) {
                    this.zoomToGraphics([feature]);
                }
            }), 100);
        },
        resetResultsGridColumns: function () {
            if (!this.resultsGrid) {
                return;
            }
            var columns = this.queryVariables.gridColumns || {
                    layerName: 'Layer',
                    foundFieldName: 'Field',
                    value: 'Result'
                };
            if (columns instanceof Array) {
                columns = array.filter(
                    columns, function (column) {
                        if (typeof column.visible === 'undefined') {
                            column.visible = true;
                        }
                        return column.visible;
                    }
                );
            }
            this.resultsGrid.setColumns(columns);
        },
        resetResultsGridSort: function () {
            if (!this.resultsGrid) {
                return;
            }
            var sort = this.queryVariables.sort || [
                    {
                        attribute: 'value',
                        descending: false
                    }
                ];
            this.resultsGrid.set('sort', sort);
        },
        resetGridSelectionMode: function () {
            if (!this.resultsGrid) {
                return;
            }
            var selectionMode = 'extended';
            this.resultsGrid.set('selectionMode', selectionMode);
        },
        zoomToSelectedGraphics: function () {
            var selectedGraphics = [];
            var selection = this.resultsGrid.selection;
            for (var id in selection) {
                if (selection.hasOwnProperty(id)) {
                    selectedGraphics.push(this.resultsGrid.row(id).data);
                }
            }
            if (selectedGraphics.length === 0) {
                return;
            }
            this.zoomToGraphics(selectedGraphics);
        },
        zoomToGraphics: function (graphics) {
            var zoomExtent = null;
            if (graphics.length > 1) {
                zoomExtent = graphicsUtils.graphicsExtent(graphics);
            } else if (graphics.length === 1) {
                zoomExtent = this.getExtentFromGraphic(graphics[0]);

                this.map.infoWindow.hide();
                this.map.infoWindow.clearFeatures();
                this.map.infoWindow.setFeatures([graphics[0]]);
                this.map.infoWindow.show(graphics[0].geometry.getCentroid());
            }
            if (zoomExtent) {
                this.setMapExtent(zoomExtent);
            }
        },
        getExtentFromGraphic: function (graphic) {
            var extent = null;
            switch (graphic.geometry.type) {
                case 'point':
                    extent = this.getExtentFromPoint(graphic);
                    break;
                default:
                    extent = graphicsUtils.graphicsExtent([graphic]);
                    break;
            }
            return extent;
        },
        getExtentFromPoint: function (point) {
            var sz = this.pointExtentSize; // hack
            var pointGeometry = point.geometry;
            return new Extent({
                'xmin': pointGeometry.x - sz,
                'ymin': pointGeometry.y - sz,
                'xmax': pointGeometry.x + sz,
                'ymax': pointGeometry.y + sz,
                'spatialReference': this.map.spatialReference
            });
        },
        setMapExtent: function (extent) {
            this.map.setExtent(extent.expand(this.zoomExtentFactor));
        },
        clearResults: function () {
            this.results = null;

            this.map.infoWindow.hide();
            this.map.infoWindow.clearFeatures();

            this.clearGraphics();
            this.clearResultsGrid();
            this.clearFeatures();

            domConstruct.empty(this.findResultsNode);
        },
        clearGraphics: function () {
            this.polygonGraphics.clear();
            this.drawToolbar.deactivate();
            this.disableStopButtons();

            this.connectMapClick();
            this.drawModeTextNode.innerText = this.i18n.labels.currentDrawModeNone;
        },
        clearResultsGrid: function () {
            if (this.resultStore) {
                this.resultsStore.setData([]);
            }
            if (this.resultsGrid) {
                this.resultsGrid.refresh();
            }
            this.findResultsNode.style.display = 'none';
            this.findResultsGrid.style.display = 'none';
        },
        clearFeatures: function () {
            if (this.graphicsLayer) {
                this.graphicsLayer.clear();
            }
        }
    });
});